import {
  ProForm,
  ProFormText,
  ProFormRadio,
  ProFormTextArea,
  ProFormUploadDragger,
  ProTable,
} from "@ant-design/pro-components";
import { ProChat } from "@ant-design/pro-chat";
import { useTheme } from "antd-style";
import ollama from "ollama/browser";
import {
  Button,
  Modal,
  Tag,
  Input,
  message,
  Card,
  Popconfirm,
  Divider,
  Radio,
} from "antd";
import React, { useState, useRef } from "react";
import { MessageFilled, PlusOutlined } from "@ant-design/icons";
import { useAsyncEffect } from "ahooks";
import dayjs from "dayjs";
import FileViewer from "@/components/FileViewer";
import Instruction from "./instruction";

export default function HomePage() {
  const { token } = useTheme();
  const [modal, setModal] = useState({
    open: false,
    footer: false,
    onCancel: () => {
      setModal((s) => ({
        ...s,
        open: false,
      }));
    },
  });

  const [list, setList] = useState([]);
  const inputRef = useRef(null);
  const [inputVisible, setInputVisible] = useState(false);
  const [inputValue, setInputValue] = useState("");

  useAsyncEffect(async () => {
    const list = await ollama.list();
    setList(list?.models);
  }, []);

  const handleInputChange = (e) => {
    setInputValue(e.target.value);
  };
  const handleInputConfirm = () => {
    if (inputValue) {
      alert(inputValue);
    }
    setInputVisible(false);
    setInputValue("");
  };
  const showInput = () => {
    setInputVisible(true);
  };

  const tagPlusStyle = {
    background: "#f0f0f0",
    borderStyle: "dashed",
  };

  //知识库 id
  const [knowledgebaseId, setKnowledgebaseId] = useState();

  //模型 id
  const [model, setModel] = useState("qwen:latest");

  const actionRef = useRef(),
    refs = useRef();

  return (
    <div style={{ height: "100%", padding: 12 }}>
      <FileViewer actionRef={actionRef}></FileViewer>
      <Modal {...modal} style={{ top: 24 }}>
        <div style={{ height: "86vh" }}>
          <ProChat
            request={async (message) => {
              // const message = { role: "user", content: "Why is the sky blue?" };
              if (model === "chatgpt3.5") {
                const response = await fetch(
                  "http://localhost:7001/api/chatgpt",
                  {
                    method: "POST",
                    headers: {
                      "Content-Type": "application/json",
                    },
                    body: JSON.stringify({ messages: message }),
                  }
                );
                return response;
              }

              if (knowledgebaseId) {
                let response = await fetch("http://localhost:7001/api/chat", {
                  method: "POST",
                  headers: {
                    "Content-Type": "application/json",
                  },
                  body: JSON.stringify({
                    knowledgebaseId,
                    model,
                    messages: message,
                  }),
                });
                console.log("====================================");
                console.log(response);
                console.log("====================================");

                const reader = response.body.getReader();
                const decoder = new TextDecoder("utf-8");
                const encoder = new TextEncoder();
                const readableStream = new ReadableStream({
                  async start(controller) {
                    function push() {
                      reader
                        .read()
                        .then(({ done, value }) => {
                          if (done) {
                            controller.close();
                            return;
                          }
                          let content = "";
                          const chunk = decoder.decode(value, { stream: true });
                          chunk.split("\n\n").forEach(async (line) => {
                            if (line) {
                              const chatMessage = JSON.parse(line);
                              content += chatMessage?.message?.content;
                            }
                          });
                          if (content !== "undefined") {
                            console.log("====================================");
                            console.log(content);
                            console.log("====================================");
                            controller.enqueue(encoder.encode(content));
                          }

                          push();
                        })
                        .catch((err) => {
                          console.error("读取流中的数据时发生错误", err);
                          controller.error(err);
                        });
                    }
                    push();
                  },
                });

                return new Response(readableStream);
              }

              const response = await ollama.chat({
                model: "qwen",
                messages: message,
                stream: true,
              });
              const encoder = new TextEncoder();
              const readableStream = new ReadableStream({
                async start(controller) {
                  async function push() {
                    const { done, value } = await response.next();
                    if (done) {
                      // 如果生成器生成的数据已经全部推送完毕，调用controller.close()结束流
                      controller.close();
                      return;
                    }
                    // 将数据推送到流中
                    controller.enqueue(encoder.encode(value?.message?.content));
                    await push();
                  }
                  await push();
                },
              });
              return new Response(readableStream);
            }}
          ></ProChat>
        </div>
      </Modal>

      <div style={{ display: "flex", marginBottom: 12, height: 33 }}>
        <Button
          icon={<MessageFilled />}
          style={{ marginRight: 8, borderRadius: 4 }}
          type="primary"
          onClick={() => {
            setModal((s) => ({
              ...s,
              open: true,
              title: model,
            }));
          }}
        ></Button>
        {list?.map((item) => {
          return (
            <Tag
              color="#13c2c2"
              className="center"
              style={{ cursor: "pointer" }}
              closable
              onClose={() => {}}
              onClick={() => {
                if (item.name === "nomic-embed-text:latest") {
                  message.warning("该模型无法对话");
                  return;
                }
                setModel(item.name);
              }}
            >
              <Radio checked={model === item.name}></Radio>
              {item?.name}
            </Tag>
          );
        })}
        <Tag
          color="#13c2c2"
          className="center"
          style={{ cursor: "pointer" }}
          closable
          onClose={() => {}}
          onClick={() => {
            setModel("chatgpt3.5");
          }}
        >
          <Radio checked={model === "chatgpt3.5"}></Radio>
          chatgpt3.5
        </Tag>
        {inputVisible ? (
          <Input
            ref={inputRef}
            type="text"
            size="small"
            style={{ width: 78, marginRight: 9 }}
            value={inputValue}
            onChange={handleInputChange}
            onBlur={handleInputConfirm}
            onPressEnter={handleInputConfirm}
          />
        ) : (
          <Tag onClick={showInput} style={tagPlusStyle} className="center">
            <PlusOutlined /> &nbsp;添加模型
          </Tag>
        )}
        <Divider
          type="vertical"
          style={{ height: "100%", marginLeft: 0 }}
        ></Divider>
        <Instruction></Instruction>
      </div>
      <div className="flex" style={{ gap: 12, justifyContent: "flex-start" }}>
        <Card
          style={{
            width: 400,
            backgroundColor: "#f9f9f9",
          }}
          hoverable
        >
          <ProForm
            autoFocusFirstInput
            grid
            onFinish={async (value) => {
              // 创建一个 FormData 对象
              const formData = new FormData();
              Object.entries(value).map(([key, value], i) => {
                if (key === "file" && value?.length > 0) {
                  value.forEach((file, index) => {
                    formData.append(`files[]`, file.originFileObj);
                  });
                } else {
                  formData.append(key, value);
                }
              });

              // 定义 Fetch 请求参数
              const requestOptions = {
                method: "POST",
                body: formData,
              };
              await fetch(
                "http://localhost:7001/api/knowledgebases",
                requestOptions
              );

              refs?.current?.reload();
            }}
            initialValues={{
              embedding: "nomic-embed-text",
            }}
            submitter={{
              submitButtonProps: {
                style: {
                  flex: 1,
                },
              },
            }}
          >
            <ProForm.Group>
              <ProFormText
                label="知识库名称"
                required
                rules={[{ required: true, message: "此项为必填项" }]}
                name="name"
                colProps={{ span: 24 }}
              ></ProFormText>
              <ProFormRadio.Group
                name="embedding"
                label="Embedding模型"
                formItemProps={{
                  rules: [{ required: true, message: "此项为必填项" }],
                }}
                options={[
                  {
                    label: "nomic-embed-text",
                    value: "nomic-embed-text",
                  },
                ]}
                required
              ></ProFormRadio.Group>
              <ProFormTextArea
                name="description"
                label="描述"
              ></ProFormTextArea>
              <ProFormUploadDragger
                name="file"
                label="知识文件"
              ></ProFormUploadDragger>
            </ProForm.Group>
          </ProForm>
        </Card>

        <ProTable
          actionRef={refs}
          style={{
            flex: 1,
          }}
          rowKey={"id"}
          cardProps={{
            hoverable: true,
            bordered: true,
            style: {
              height: 623,
              backgroundColor: "#f9f9f9",
            },
          }}
          search={{
            filterType: "light",
            placement: "bottom",
          }}
          headerTitle="知识库列表"
          columns={[
            {
              title: "知识库",
              dataIndex: "name",
              key: "name",
              search: false,
            },
            {
              title: "文件",
              dataIndex: "files",
              key: "files",
              search: false,
              render: (text, row) => {
                return row?.files?.map?.((it, i) => {
                  return (
                    <Tag
                      color="#13c2c2"
                      onClick={() => {
                        actionRef?.current?.open(
                          "http://localhost:7001" + it?.url,
                          it.name
                        );
                      }}
                    >
                      {it.name}
                    </Tag>
                  );
                });
              },
            },
            {
              title: "Embedding模型",
              dataIndex: "embedding",
              key: "embedding",
              search: false,
            },
            {
              title: "描述",
              dataIndex: "description",
              key: "description",
              search: false,
            },
            {
              title: "创建时间",
              dataIndex: "created",
              key: "created",
              render: (text, row) => {
                return dayjs(row.created).format("YYYY-MM-DD HH:mm:ss");
              },
              search: false,
            },
            {
              title: "操作",
              valueType: "option",
              render: (text, row) => {
                return (
                  <Popconfirm
                    title="是否删除该知识库"
                    placement="bottomRight"
                    onConfirm={async (e) => {
                      let res = await fetch(
                        "http://localhost:7001/api/knowledgebases/" + row?.id,
                        {
                          method: "DELETE",
                        }
                      );
                      res = await res.json();
                      if (res.code === 0) {
                        message.success("删除成功");
                        refs.current.reload();
                      }
                    }}
                  >
                    <Button
                      size="small"
                      type="text"
                      danger
                      onClick={(e) => {
                        e.stopPropagation(); // prevent
                      }}
                    >
                      删除
                    </Button>
                  </Popconfirm>
                );
              },
            },
          ]}
          request={async (params) => {
            let res = await fetch("http://localhost:7001/api/knowledgebases", {
              method: "GET",
            });
            res = await res.json();
            return (
              res ?? {
                data: [],
              }
            );
          }}
          onRow={(record) => ({
            onClick: (event) => {
              setKnowledgebaseId(record.id);
            },
          })}
          rowSelection={{
            type: "radio",
            selectedRowKeys: knowledgebaseId ? [knowledgebaseId] : [],
            onChange: (key) => {
              setKnowledgebaseId(key[0]);
            },
          }}
        ></ProTable>
      </div>
    </div>
  );
}
